#ifndef ZPP_WORK_QUEUE_HPP__
#define ZPP_WORK_QUEUE_HPP__

#include <chrono>
#include <tuple>
#include <zephyr/kernel.h>
#include <zpp/callback.hpp>
#include <zpp/error.hpp>
#include <zpp/assert.hpp>

namespace zpp {

class work : public k_work_delayable {
public:
  template <typename t_callable> work(t_callable handler) : m_handler(handler) {
    ZPP_ASSERT_OK(k_work_init_delayable(this, k_work_callback));
  }

  auto submit() -> zpp::error {
    const auto ret = k_work_schedule(this, K_NO_WAIT);
    return zpp::error{ret};
  }
  template <typename t_rep, typename t_period>
  auto submit(std::chrono::duration<t_rep, t_period> delay) -> zpp::error {
    const auto ms =
        std::chrono::duration_cast<std::chrono::milliseconds>(delay);
    const auto ret = k_work_schedule(this, K_MSEC(ms.count()));
    return zpp::error{ret};
  }

private:
  static auto k_work_callback(k_work *work_item) -> void {
    auto *work =
        reinterpret_cast<zpp::work *>(k_work_delayable_from_work(work_item));
    work->m_handler();
  }
  zpp::callback<void()> m_handler;
};

} // namespace zpp

#endif // ZPP_WORK_QUEUE_HPP__